#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>

#include <linux/of.h>


// 设备节点匹配表
const static struct of_device_id mynode_of_match[] = {
    {.compatible = "my device_tree"},
    {},
};

static struct property *pprop; 

int elem_num;
u32 value_u32;
u64 value_u64;
u32 out_value[2];
const char *value_string;


// 平台设备探测函数
// 当系统检测到一个平台设备与该驱动程序匹配时，该 函数将被调用以初始化和配置设备。  
int my_platform_probe(struct platform_device *pdev)
{
    struct device_node *pn;
    printk(KERN_EMERG "my_platform_probe: Probing platform device!\n");
    /* 设备特定操作 */


    // ● 通过名字获得设备节点
    pn = of_find_node_by_name(NULL, "myLed");
    printk(KERN_EMERG "my device_node is %s \n", pn->name);



    // ● 通过设备节点 的指定名称获取属性。 
    // 查找compatible属性
    pprop = of_find_property(pn, "compatible", NULL);
    printk(KERN_EMERG "my device_node propertity is [%s] \n", pprop->name);

    // ● 通过设备节点的指定名称获取属性的数量。
    // 获取reg属性的元素数量
    elem_num = of_property_count_elems_of_size(pn, "reg", 4);
    printk(KERN_EMERG "my device_node propertity [reg]  num is %d\n", elem_num);

    // ● 通过设备节点 的指定名称，并指定索引值，获取属性值。
    // 读取reg属性的值
    of_property_read_u32_index(pn, "reg", 0, &value_u32);
    of_property_read_u64_index(pn, "reg", 0, &value_u64);
    printk(KERN_EMERG "my device_node propertity [reg] is 0x%X\n", value_u32);
    printk(KERN_EMERG "my device_node propertity [reg] is 0x%llX\n", value_u64);

    // ● 通过设备节点 的指定名称，获取指定长度数组。
    // 读取reg属性的变长数组
    of_property_read_variable_u32_array(pn, "reg", out_value, 1, 2);
    printk(KERN_EMERG "my device_node propertity [reg][0] is 0x%X\n", out_value[0]);
    printk(KERN_EMERG "my device_node propertity [reg][1] is 0x%X\n", out_value[1]);

    // ● 通过设备节点 的指定名称，获取字符串。
    // 读取compatible属性的字符串值
    of_property_read_string(pn, "compatible", &value_string);
    printk(KERN_EMERG "my device_node propertity [compatible] is %s\n", value_string);

    return 0;
}

// 平台设备移除函数
// 当平台设备从系统中移除时，该函数将被调用以执行 清理和释放资源的操作。
int my_platform_remove(struct platform_device *pdev)
{
    printk(KERN_EMERG "my_platform_remove: Remove platform device!\n");
    /* 设备特定操作 */

    return 0;
}

// 平台设备关闭函数
// 当系统关闭时，该函数将被调用以执行与平台设备 相关的关闭操作。 
void my_platform_shutdown(struct platform_device *pdev)
{
    printk(KERN_EMERG "my_platform_shutdown: Shutdown platform device!\n");
    /* 设备特定操作 */

    
}
// 平台设备挂起函数
// 当系统进入挂起状态时，该函数将被调用以执行与 平台设备相关的挂起操作。
int my_platform_suspend(struct platform_device *pdev, pm_message_t state)
{
    printk(KERN_EMERG "my_platform_suspend: Suspend platform device!\n");
    /* 设备特定操作 */

    return 0;
}
// 平台设备恢复函数
// 当系统从挂起状态恢复时，该函数将被调用以执行与 平台设备相关的恢复操作。  
int my_platform_resume(struct platform_device *pdev)
{
    printk(KERN_EMERG "my_platform_resume: Resume platform device!\n");
    /* 设备特定操作 */

    return 0;
}


const struct of_device_id of_match_table_id[] = {
    {.compatible = "my device_tree"},
    {},
};


static struct platform_driver my_platform_driver = {
    .probe = my_platform_probe,
    .remove = my_platform_remove,
    .shutdown = my_platform_shutdown,
    .suspend = my_platform_suspend,
    .resume = my_platform_resume,

    .driver = {
        .name = "my_platform_GPIO",
        .owner = THIS_MODULE,
        .of_match_table = of_match_table_id,
    },
};


static int __init my_platform_device_init(void)
{   
    int ret;

    // 注册平台驱动
    ret = platform_driver_register(&my_platform_driver);
     if (ret < 0)
    {
        printk(KERN_EMERG "Failed platform_driver_register.\n");
        return ret;
    }

    printk(KERN_EMERG "platform_driver_register OK!\n");

    return 0;
}



static void __exit my_platform_device_exit(void)
{
    platform_driver_unregister(&my_platform_driver);// 注销平台驱动
    printk(KERN_EMERG "platform_driver_unregister OK!\n");
}



module_init(my_platform_device_init);
module_exit(my_platform_device_exit);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Treasure1029");










